-- c25Board.vhd
--
-- entity    c25Board    -generic wrapper for Altera CycloneIII 3c25
--                 Nios2 prototyping board
-- architecture    wrapper
--
-- usage:    1. I/O setup    in entity
--                -comment out all unused ports!!!
--                -due to device resources (of FPGA) not all
--                 inputs/outputs are possible in one design!!!
--        2. declare    in architecture
--                -components to be used, see <myComponent>
--                -local signals
--        3. statements    in architecture
--                -component instances
--                -processes
--        4. Quartus    in file: c25Board.qsf
--                -add VHDL source files
--                -if needed; change pin layout
--               or    GUI-setup within quartus
--------------------------------------------------------------------------------
library ieee;                    -- packages:
library std;
use ieee.std_logic_1164.all;            --   std_logic
use ieee.numeric_std.all;            --   (un)signed
--use work.all;
use work.constants.all;
use IEEE.std_logic_textio.all;
--use std.standard.all;
use std.textio.all;

-- entity    ----------------------------------------------------------------
--------------------------------------------------------------------------------
entity c25Board is
port (    
    oscClock50_i    : in    std_logic;
    cpuResetN_i        : in    std_logic;
--    reconfig_i        : in    std_logic;

--    user I/O: buttons+LED    ------------------------------------------------
    buttonN_i        : in    std_logic_vector(4 downto 1);
    ledN_o            : out    std_logic_vector(4 downto 1);

--    Flash    32M x16        ------------------------------------------------
--            ==>    flash_sramData_b(15 downto 0);
--    flashWeN_o        : out    std_logic;
--    flashCsN_o        : out    std_logic;
--    flashOeN_o        : out    std_logic;
--    flashResetN_o        : out    std_logic;
--    flashAdvN_o        : out    std_logic;
--    flashClk_o        : out    std_logic;
--    flashWait_o        : out    std_logic;

--    SSRAM    256k x32    ------------------------------------------------
--            ==>    flash_sramAddr_o(22 downto 2);
    sramOeN_o        : out    std_logic;
    sramCeN_o        : out    std_logic; -- 0
    sramWeN_o        : out    std_logic;
    sramBeN_o        : out    std_logic_vector(3 downto 0); -- 0000 fuer alle bytes
    sramAdscN_o        : out    std_logic; -- 1
    sramClk_o        : out    std_logic;

--    FLASH+SSRAM        ------------------------------------------------
--    flash_sramAddr_o    : out    std_logic_vector(25 downto 1);
    flash_sramAddr_o    : out    std_logic_vector(23 downto 0);
    flash_sramData_b    : inout    std_logic_vector(31 downto 0)

--    DDR SDRAM  4M x16 x4    ------------------------------------------------
--    ddrDqs_b        : inout    std_logic_vector( 1 downto 0);
--    ddrDm_o            : out    std_logic_vector( 1 downto 0);
--    ddrBa_o            : out    std_logic_vector( 1 downto 0);
--    ddrCasN_o        : out    std_logic;
--    ddrCke_o        : out    std_logic;
--    ddrCsN_o        : out    std_logic;
--    ddrRasN_o        : out    std_logic;
--    ddrWeN_o        : out    std_logic;
--    ddrClkP_b        : inout    std_logic;
--    ddrClkN_b        : inout    std_logic;
--    ddrAddr_o        : out    std_logic_vector(12 downto 0);
--    ddrData_b        : inout    std_logic_vector(15 downto 0);

--    HSMC I/O        ------------------------------------------------
--            ==>    naming scheme from "Starter Board" manual
--            ==>    use I/O from daugther board below!!! =>    hc...
--    hsmcSda_b        : inout    std_logic;
--    hsmcScl_b        : inout    std_logic;
--    hsmcTck_i        : in    std_logic;
--    hsmcTms_i        : in    std_logic;
--    hsmcTdi_i        : in    std_logic;
--    hsmcTdo_o        : out    std_logic;
--    hsmcClk0_o        : out    std_logic;
--    hsmcClk0_i        : in    std_logic;
--    hsmcClkP_o        : out    std_logic_vector( 1 to 2);
--    hsmcClkP_i        : in    std_logic_vector( 1 to 2);
--    hsmcClkN_o        : out    std_logic_vector( 1 to 2);
--    hsmcClkN_i        : in    std_logic_vector( 1 to 2);
--    hsmcData_b        : inout    std_logic_vector(19 downto 0);
--    hsmcTxP_b        : inout    std_logic_vector(16 downto 4);
--    hsmcRxP_b        : inout    std_logic_vector(16 downto 4);
--    hsmcTxN_b        : inout    std_logic_vector(16 downto 4);
--    hsmcRxN_b        : inout    std_logic_vector(16 downto 4);

--    LCD touch panel        ------------------------------------------------
--    hcVd_o            : out    std_logic;
--    hcHd_o            : out    std_logic;
--    hcDen_o            : out    std_logic;
--    hcNClk_o        : out    std_logic;
--    hcLcdData_o        : out    std_logic_vector( 7 downto 0);
--    hcGReset_o        : out    std_logic;
--    hcScen_o        : out    std_logic;
--    hcSda_b            : inout    std_logic;
--    hcAdcDClk_o        : out    std_logic;
--    hcAdcDIn_o        : out    std_logic;
--    hcAdcCsN_o        : out    std_logic;
--    hcAdcDOut_i        : in    std_logic;
--    hcAdcPenirqN_i        : in    std_logic;
--    hcAdcBusy_i        : in    std_logic;

--    Audio Codec        ------------------------------------------------
--    hcAudBClk_o        : out    std_logic;
--    hcAudXClk_o        : out    std_logic;
--    hcAudDacData_o        : out    std_logic;
--    hcAudDacLrClk_o        : out    std_logic;
--    hcAudAdcData_i        : in    std_logic;
--    hcAudAdcLrClk_o        : out    std_logic;
--    hcI2cData_b        : inout    std_logic;
--    hcI2cClk_o        : out    std_logic;

--    SD Card Interface    ------------------------------------------------
--    hcSdDat3_b        : inout    std_logic;
--    hcSdCmd_b        : inout    std_logic;
--    hcSdClk_o        : out    std_logic;
--    hcSdDat_b        : inout    std_logic;

--    Ethernet PHY        ------------------------------------------------
--    hcTxClk_i        : in    std_logic;
--    hcTxEn_o        : out    std_logic;
--    hcTxData_o        : out    std_logic_vector( 3 downto 0);
--    hcEthResetN_o        : out    std_logic;
--    hcMdIo_b        : inout    std_logic;
--    hcMdClk_o        : out    std_logic;
--    hcRxClk_o        : in    std_logic;
--    hcRxDv_o        : in    std_logic;
--    hcRxCrs_o        : in    std_logic;
--    hcRxErr_o        : in    std_logic;
--    hcRxCol_o        : in    std_logic;
--    hcRxData_i        : in    std_logic_vector( 3 downto 0);

--    RS232 Serial Interface    ------------------------------------------------
--    hcUartRxData_i        : in    std_logic;
--    hcUartTxData_o        : out    std_logic;

--    PS/2 Interface        ------------------------------------------------
--    hcPS2Clk_b        : inout    std_logic;
--    hcPS2Data_b        : inout    std_logic;

--    Video Decoder Interface    ------------------------------------------------
--    hcTdData_i        : in    std_logic_vector( 7 downto 0);
--    hcTd27MHz_i        : in    std_logic;
--    hcTdReset_o        : out    std_logic;
----    hcI2cData_b        : inout    std_logic;
----    hcI2cClk_o        : out    std_logic;
--    hcTdVs_i        : in    std_logic;
--    hcTdHs_i        : in    std_logic;

--    VGA DAC Interface    ------------------------------------------------
--    hcVgaData_o        : out    std_logic_vector( 9 downto 0);
--    hcVgaBlank_o        : out    std_logic;
--    hcVgaSync_o        : out    std_logic;
--    hcVgaClk_o        : out    std_logic;
--    hcVgaHs_o        : out    std_logic;
--    hcVgaVs_o        : out    std_logic;

--    I2C Serial EEPROM    ------------------------------------------------
--    hcIdI2cClk_o        : out    std_logic;
--    hcIdI2cData_b        : inout    std_logic
    );
end entity c25Board;

-- architecture    ----------------------------------------------------------------
architecture wrapper of c25Board is
    type RamType is array(0 to 2**progMemSizeBits) of b32;
    constant progFile : string := "program.mif";
    signal progMem : RamType;
     attribute ram_init_file : string;
    attribute ram_init_file of progMem : signal is progFile; 
    
    signal imemAddr, imemData, dmemAddrRead, dmemAddrWrite, dmemDataRead, dmemDataWrite : b32;
    signal dmemWrEna, dmemRdEna, cpuWait : std_logic;
    signal dmemNByteMask : std_logic_vector(3 downto 0);
    signal leds : std_logic_vector(3 downto 0);
    
begin
    cpu0: entity work.cpu port map(clock => oscClock50_i, resetN => cpuResetN_i, imemAddr => imemAddr,
        imemData => imemData, dmemAddrRead => dmemAddrRead, dmemAddrWrite => dmemAddrWrite,
        dmemWrEna => dmemWrEna, dmemDataRead => dmemDataRead, dmemDataWrite=> dmemDataWrite,
        dmemRdEna => dmemRdEna, dmemNByteMask => dmemNByteMask, doWait => cpuWait);
        
    cpuWait <= '0';
    imemData <= progMem(to_integer(unsigned(imemAddr(progMemSizeBits - 1 downto 0))));
    ledN_o(4 downto 1) <= leds;        
        
--    progMemP : process(oscClock50_i)
--    begin        
--       if rising_edge(oscClock50_i) then
--            imemData <= progMem(to_integer(unsigned(imemAddr(progMemSizeBits - 1 downto 0))));
--        end if;        
--    end process;    
    
    -----------------[data memory(sram)]------------------------
    sramClk_o <= oscClock50_i;
    sramAdscN_o <= '0';    -- disable funny sram modes                        
    sramBeN_o <= dmemNByteMask;
    
    
    sramCeN_o <= '0' when  dmemAddrRead(31) = '0' or dmemAddrWrite(31) = '0' else '1';

    -- sram read        
    sramOeN_o <= '0' when                 dmemAddrRead(31) = '0'   and dmemRdEna = '1' and dmemWrEna = '0' else '1';    
    flash_sramAddr_o <= dmemAddrRead(23 downto 0)
                                     when dmemAddrRead(31) = '0'   and dmemRdEna = '1' and dmemWrEna = '0' else (others => 'Z');    
    dmemDataRead <= flash_sramData_b when dmemAddrRead(31) = '0'   and dmemRdEna = '1' and dmemWrEna = '0' else (others => 'Z');    

    -- sram write
    sramWeN_o <= '0' when                  dmemAddrWrite(31) = '0' and dmemRdEna = '0' and dmemWrEna = '1' else '1';    
    flash_sramAddr_o <= dmemAddrWrite(23 downto 0)                                                                              
                                      when dmemAddrWrite(31) = '0' and dmemRdEna = '0' and dmemWrEna = '1' else (others => 'Z');
    flash_sramData_b <= dmemDataWrite when dmemAddrWrite(31) = '0' and dmemRdEna = '0' and dmemWrEna = '1' else (others => 'Z');

    -- buttons read
    dmemDataRead(3 downto 0) <= buttonN_i(4 downto 1)
                                      when dmemAddrRead(31) = '1'  and dmemRdEna = '1' and dmemWrEna = '0' else (others => 'Z');

    procLedsReg : process(oscClock50_i)
    begin                
        if rising_edge(oscClock50_i) then
            if dmemAddrWrite(31) = '1' and dmemRdEna = '0' and dmemWrEna = '1' then
                leds <= std_logic_vector(not signed(dmemDataWrite(3 downto 0)));
            end if;
        end if;
    end process procLedsReg;
    
-- the first one is an altera pragma and the second is for xilinx
-- synthesis translate_off 
-- pragma translate_off
    read_input_file : process
            variable inline : line;
            variable character_variable : character := ' ';
            variable end_of_line: boolean;
            file myfile:text is progFile;
            variable bitNum : integer := 0;
            variable addr : unsigned(7 downto 0);
            variable data : unsigned(31 downto 0);
    begin    
        -- skip first 6 lines
        for i in 1 to 6 loop
            readline(myfile, inline);
        end    loop;
        
        mainLineLoop: while not endfile(myfile) loop
            readline(myfile, inline);    
            
            bitNum := 7;
            addr := (others => '0');
            while character_variable /= ':' loop
                read(inline, character_variable, end_of_line);
                if character_variable = 'E' then -- the beginning of 'END' statement
                    exit mainLineLoop;                    
                elsif character_variable = '1' then
                    addr(bitNum) := '1';
                    bitNum := bitNum - 1;
                elsif character_variable = '0' then 
                    addr(bitNum) := '0';
                    bitNum := bitNum - 1;
                end if;                
            end loop;        

            report "address: " & integer'image(to_integer(addr));

            bitNum := 31;
            while end_of_line loop
                read(inline, character_variable, end_of_line);                                
                if character_variable = '1' then
                    data(bitNum) := '1';
                    bitNum := bitNum - 1;
                elsif character_variable = '0' then 
                    data(bitNum) := '0';
                    bitNum := bitNum - 1;
                end if;
            end loop;
            progMem(to_integer(addr)) <= std_logic_vector(data);            
            
        end loop mainLineLoop;
        file_close(myfile);
        wait;    --Do nothing when finished
    end process read_input_file;
-- synthesis translate_on
-- pragma translate_on
end architecture wrapper;
